//
// Created by admin on 2021/2/17.
//

#include "InstancedItemPass.h"
#include "Scene.h"
#include "EngineCore.h"
#include "Camera.h"
#include "RenderItem.h"
#include "RenderItemStaticOpaque.h"
#include "RenderItemInstanced.h"
#include "Model.h"
#include "Texture.h"
#include "ComputePass.h"
#include "Buffer.h"

InstancedItemPass<GraphicsAPI::GLESv3>::InstancedItemPass()
{

}


void InstancedItemPass<GraphicsAPI::GLESv3>::Draw()
{
    GL_CHECK(glUseProgram(program));
    auto curr_scene = SceneMgr::GetInstance()->GetCurrentScene();
    auto main_cam = curr_scene->GetMainCamera();

    auto vp_matrix = GL_CHECK(main_cam->GetProjMatrix() * main_cam->GetViewMatrix());
    auto camera_vp_matrix = vp_matrix;
    GLfloat * camera_matrix_value = glm::value_ptr(camera_vp_matrix);
    GL_CHECK(glUniformMatrix4fv(CameraVPMatrix_location, 1, false, camera_matrix_value));

    GL_CHECK(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, rwBuffer->GetBuffer()));

    for (auto iter = curr_scene->GetInstancedItemBegin(); iter != curr_scene->GetInstancedItemEnd(); ++ iter)
    {
        auto gles_item = std::dynamic_pointer_cast<RenderItemInstanced<GraphicsAPI::GLESv3>>(*iter);

        GL_CHECK(glBindVertexArray(gles_item->GetVAO()));
        std::shared_ptr<Texture2D<GraphicsAPI::GLESv3>> tex = std::dynamic_pointer_cast<Texture2D<GraphicsAPI::GLESv3>>(gles_item->GetTexture(0));
        GL_CHECK(glActiveTexture(tex->GetTextureUnit()));
        GL_CHECK(glBindTexture(GL_TEXTURE_2D, tex->GetTexture()));
        GL_CHECK(glDrawElementsInstanced(GL_TRIANGLES, gles_item->GetModel()->GetFaceNumber() * 3, gles_item->GetModel()->GetIndexType(), 0, gles_item->GetInstancedNumber()));
        GL_CHECK(glBindVertexArray(0));
    }
}


void InstancedItemPass<GraphicsAPI::GLESv3>::InitShaderUniformLocation()
{
    GL_CHECK(glUseProgram(program));
    CameraVPMatrix_location = GL_CHECK(glGetUniformLocation(program, "CameraVPMatrix"));

    LOGI("InstancedItemPass CameraVPMatrix_location = %d",
         CameraVPMatrix_location);

    assert(CameraVPMatrix_location >= 0);

    GL_CHECK(glUseProgram(0));

    std::shared_ptr<ComputePass<GraphicsAPI::GLESv3>> cs = std::dynamic_pointer_cast<ComputePass<GraphicsAPI::GLESv3>>( g_engine->GetPass(3));
    rwBuffer = cs->GetBuffer();
}